package com.bravo.other.geoid;

import java.util.Map;

/**
 * Simple Geoid Height Calculation Example
 * Demonstrates practical usage of the geoid height calculator
 * 
 * @author bravo
 */
public class SimpleGeoidExample {
    
    public static void main(String[] args) {
        System.out.println("=== Simple Geoid Height Calculation Example ===\n");
        
        // Example 1: Calculate geoid height for Beijing
        calculateForCity("Beijing", 39.9042, 116.4074);
        
        // Example 2: Calculate geoid height for Shanghai
        calculateForCity("Shanghai", 31.2304, 121.4737);
        
        // Example 3: Calculate geoid height for Guangzhou
        calculateForCity("Guangzhou", 23.1291, 113.2644);
        
        // Example 4: Calculate geoid height for a custom location
        calculateForCustomLocation("Custom Point", 40.0, 120.0);
        
        // Example 5: User specified coordinates
        System.out.println("=== USER SPECIFIED COORDINATES ===");
        calculateForUserCoordinates("User Location", 30.85816, 120.18562);
        
        System.out.println("\n=== Summary ===");
        System.out.println("The geoid height represents the difference between:");
        System.out.println("- Geoid surface (mean sea level)");
        System.out.println("- Ellipsoid surface (mathematical model of Earth)");
        System.out.println();
        System.out.println("Negative values indicate the geoid is below the ellipsoid.");
        System.out.println("Positive values indicate the geoid is above the ellipsoid.");
        System.out.println();
        System.out.println("Typical geoid heights range from -100m to +100m globally.");
        System.out.println("In China, geoid heights are generally between -50m and +20m.");
    }
    
    /**
     * Calculate geoid height for user specified coordinates
     */
    private static void calculateForUserCoordinates(String locationName, double latitude, double longitude) {
        System.out.println("--- " + locationName + " ---");
        System.out.printf("Coordinates: Latitude %.5f°, Longitude %.5f°\n", latitude, longitude);
        System.out.println("Note: This is the location you specified!");
        System.out.println();
        
        try {
            // Method 1: EGM2008 model
            double egm2008 = GeoidHeightCalculator.calculateEGM2008(latitude, longitude);
            System.out.printf("EGM2008 Model: %.6f meters\n", egm2008);
            
            // Method 2: EGM96 model
            double egm96 = GeoidHeightCalculator.calculateEGM96(latitude, longitude);
            System.out.printf("EGM96 Model:  %.6f meters\n", egm96);
            
            // Method 3: Interpolation (if control points available)
            try {
                Map<GeoidHeightCalculator.Coordinate, Double> controlPoints = 
                    GeoidHeightCalculator.createSampleControlPoints();
                double interpolation = GeoidHeightCalculator.calculateByInterpolation(
                    latitude, longitude, controlPoints);
                System.out.printf("Interpolation: %.6f meters\n", interpolation);
            } catch (Exception e) {
                System.out.println("Interpolation: Not available");
            }
            
            // Method 4: Advanced EGM2008 with different degrees
            double advanced5 = AdvancedGeoidCalculator.calculateEGM2008Complete(latitude, longitude, 5);
            double advanced10 = AdvancedGeoidCalculator.calculateEGM2008Complete(latitude, longitude, 10);
            double advanced20 = AdvancedGeoidCalculator.calculateEGM2008Complete(latitude, longitude, 20);
            double advanced30 = AdvancedGeoidCalculator.calculateEGM2008Complete(latitude, longitude, 30);
            
            System.out.println("\nAdvanced EGM2008 Results (Different Degrees):");
            System.out.printf("  5 degrees:  %.6f meters\n", advanced5);
            System.out.printf("  10 degrees: %.6f meters\n", advanced10);
            System.out.printf("  20 degrees: %.6f meters\n", advanced20);
            System.out.printf("  30 degrees: %.6f meters\n", advanced30);
            
            // Method 5: Calculate gradient and curvature
            double[] gradient = AdvancedGeoidCalculator.calculateGeoidGradient(latitude, longitude, 0.001);
            double[][] curvature = AdvancedGeoidCalculator.calculateGeoidCurvature(latitude, longitude, 0.001);
            
            System.out.println("\nGradient Analysis:");
            System.out.printf("  Latitude gradient:  %.6f m/°\n", gradient[0]);
            System.out.printf("  Longitude gradient: %.6f m/°\n", gradient[1]);
            System.out.printf("  Gradient magnitude: %.6f m/°\n", 
                Math.sqrt(gradient[0]*gradient[0] + gradient[1]*gradient[1]));
            
            System.out.println("\nCurvature Analysis:");
            System.out.printf("  d²N/dlat²:    %.6f m/°²\n", curvature[0][0]);
            System.out.printf("  d²N/dlatdlon: %.6f m/°²\n", curvature[0][1]);
            System.out.printf("  d²N/dlon²:    %.6f m/°²\n", curvature[1][1]);
            
            // Comparison with online tool
            System.out.println("\n=== COMPARISON WITH ONLINE TOOL ===");
            System.out.println("Online tool result: approximately 10 meters");
            System.out.println("Our calculation results:");
            System.out.printf("  EGM2008: %.6f meters\n", egm2008);
            System.out.printf("  EGM96:   %.6f meters\n", egm96);
            System.out.printf("  Advanced EGM2008 (20°): %.6f meters\n", advanced20);
            
            double differenceEGM2008 = Math.abs(egm2008 - 10.0);
            double differenceEGM96 = Math.abs(egm96 - 10.0);
            double differenceAdvanced = Math.abs(advanced20 - 10.0);
            
            System.out.println("\nDifferences from online tool:");
            System.out.printf("  EGM2008: %.6f meters\n", differenceEGM2008);
            System.out.printf("  EGM96:   %.6f meters\n", differenceEGM96);
            System.out.printf("  Advanced EGM2008 (20°): %.6f meters\n", differenceAdvanced);
            
        } catch (Exception e) {
            System.err.println("Calculation failed: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    /**
     * Calculate geoid height for a specific city
     */
    private static void calculateForCity(String cityName, double latitude, double longitude) {
        System.out.println("--- " + cityName + " ---");
        System.out.printf("Coordinates: %.4f°N, %.4f°E\n", latitude, longitude);
        
        try {
            // Method 1: EGM2008 model
            double egm2008 = GeoidHeightCalculator.calculateEGM2008(latitude, longitude);
            System.out.printf("EGM2008 Model: %.6f meters\n", egm2008);
            
            // Method 2: EGM96 model
            double egm96 = GeoidHeightCalculator.calculateEGM96(latitude, longitude);
            System.out.printf("EGM96 Model:  %.6f meters\n", egm96);
            
            // Method 3: Interpolation (if control points available)
            try {
                Map<GeoidHeightCalculator.Coordinate, Double> controlPoints = 
                    GeoidHeightCalculator.createSampleControlPoints();
                double interpolation = GeoidHeightCalculator.calculateByInterpolation(
                    latitude, longitude, controlPoints);
                System.out.printf("Interpolation: %.6f meters\n", interpolation);
            } catch (Exception e) {
                System.out.println("Interpolation: Not available");
            }
            
            // Method 4: Advanced EGM2008 with different degrees
            double advanced5 = AdvancedGeoidCalculator.calculateEGM2008Complete(latitude, longitude, 5);
            double advanced20 = AdvancedGeoidCalculator.calculateEGM2008Complete(latitude, longitude, 20);
            System.out.printf("Advanced EGM2008 (5°):  %.6f meters\n", advanced5);
            System.out.printf("Advanced EGM2008 (20°): %.6f meters\n", advanced20);
            
        } catch (Exception e) {
            System.err.println("Calculation failed: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    /**
     * Calculate geoid height for a custom location
     */
    private static void calculateForCustomLocation(String locationName, double latitude, double longitude) {
        System.out.println("--- " + locationName + " ---");
        System.out.printf("Coordinates: %.4f°N, %.4f°E\n", latitude, longitude);
        
        try {
            // Calculate using different models
            double egm2008 = GeoidHeightCalculator.calculateEGM2008(latitude, longitude);
            double egm96 = GeoidHeightCalculator.calculateEGM96(latitude, longitude);
            
            System.out.printf("EGM2008 Model: %.6f meters\n", egm2008);
            System.out.printf("EGM96 Model:  %.6f meters\n", egm96);
            
            // Calculate gradient and curvature using advanced calculator
            double[] gradient = AdvancedGeoidCalculator.calculateGeoidGradient(latitude, longitude, 0.001);
            double[][] curvature = AdvancedGeoidCalculator.calculateGeoidCurvature(latitude, longitude, 0.001);
            
            System.out.println("Gradient Analysis:");
            System.out.printf("  Latitude gradient:  %.6f m/°\n", gradient[0]);
            System.out.printf("  Longitude gradient: %.6f m/°\n", gradient[1]);
            System.out.printf("  Gradient magnitude: %.6f m/°\n", 
                Math.sqrt(gradient[0]*gradient[0] + gradient[1]*gradient[1]));
            
            System.out.println("Curvature Analysis:");
            System.out.printf("  d²N/dlat²:    %.6f m/°²\n", curvature[0][0]);
            System.out.printf("  d²N/dlatdlon: %.6f m/°²\n", curvature[0][1]);
            System.out.printf("  d²N/dlon²:    %.6f m/°²\n", curvature[1][1]);
            
        } catch (Exception e) {
            System.err.println("Calculation failed: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    /**
     * Demonstrate practical application scenarios
     */
    public static void demonstrateApplications() {
        System.out.println("=== Practical Applications ===");
        
        // Scenario 1: GPS elevation correction
        System.out.println("1. GPS Elevation Correction:");
        System.out.println("   GPS provides ellipsoid height, but we often need orthometric height.");
        System.out.println("   Orthometric Height = Ellipsoid Height - Geoid Height");
        System.out.println();
        
        // Scenario 2: Surveying and mapping
        System.out.println("2. Surveying and Mapping:");
        System.out.println("   Converting between different height systems");
        System.out.println("   Ensuring consistency across survey networks");
        System.out.println();
        
        // Scenario 3: Engineering projects
        System.out.println("3. Engineering Projects:");
        System.out.println("   Bridge and tunnel construction");
        System.out.println("   Pipeline and road design");
        System.out.println("   Flood control and water management");
        System.out.println();
        
        // Scenario 4: Scientific research
        System.out.println("4. Scientific Research:");
        System.out.println("   Geodesy and geophysics");
        System.out.println("   Oceanography and climate studies");
        System.out.println("   Satellite altimetry");
        System.out.println();
    }
}
